﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Business.Common.Exceptions;
using Common.Logger;
using DataAccess.Exceptions;

namespace Business.Common.Service.Response
{
    public class Response
    {
        public ResponseEnumeration.Code ResponseCode { get; set; }
        public string ResponseDescription { get; set; }
        public List<ResponseError> ResponseErrors { get; set; }

        public Response()
        {
            ResponseCode = ResponseEnumeration.Code.OK;
            ResponseDescription = "";
            ResponseErrors = new List<ResponseError>();
        }

        public void SetOKResponse(string description = "")
        {
            ResponseCode = ResponseEnumeration.Code.OK;
            ResponseDescription = description;
        }

        # region General Error Setters

        public bool HasErrors()
        {
            return ResponseErrors.Count > 0;
        }

        private void SetError(Exception ex, ResponseEnumeration.Code code)
        {
            SetResponseError(ex, code);
            LogException(ex, code);
        }

        protected void LogException(Exception ex, ResponseEnumeration.Code code)
        {
            try
            {
                IDNPCLogger logger = DNPCLogManager.GetDNPCLogger();
                logger.LogException("Error code: " + code.ToString(), ex);
            }
            catch (Exception exception)
            {
                SetResponseError(exception, code);
            }
        }

        protected void SetResponseError(Exception ex, ResponseEnumeration.Code code, String title = null)
        {
            ResponseCode = code;
            ResponseErrors.Add(new ResponseError() { Description = ex.Message, Title = title });
            if (ResponseDescription.Length == 0)
            {
                ResponseDescription = ex.Message;
            }
            else
            {
                ResponseDescription += "<br>" + ex.Message;
            }
        }

        private void AddError(Exception ex, ResponseEnumeration.Code code)
        {
            SetResponseError(ex, code);
            LogException(ex, code);
        }

        # endregion

        # region Specific Error Setters

        public void SetBusinessError(Exception ex, string title = null)
        {
            SetResponseError(ex, ResponseEnumeration.Code.BUSINESS_ERROR, title);
        }

        public void SetBadRequestError(Exception ex)
        {
            SetError(ex, ResponseEnumeration.Code.BAD_REQUEST);
        }

        public void SetInternalServerError(Exception ex)
        {
            SetError(ex, ResponseEnumeration.Code.INTERNAL_SERVER_ERROR);
        }

        public void AddNotFoundError(Exception ex)
        {
            AddError(ex, ResponseEnumeration.Code.NOT_FOUND);
        }

        public void AddBusinessError(Exception ex)
        {
            AddError(ex, ResponseEnumeration.Code.BUSINESS_ERROR);
        }

        private void AddInternalServerError(Exception ex)
        {
            AddError(ex, ResponseEnumeration.Code.INTERNAL_SERVER_ERROR);
        }

        private void AddBadRequestError(Exception ex)
        {
            AddError(ex, ResponseEnumeration.Code.BAD_REQUEST);
        }

        # endregion

        # region Handle Exceptions

        public void HandleException(Exception ex)
        {
            if (ex is EntityNotFoundException)
            {
                this.AddNotFoundError(ex);
                return;
            }
            if (ex is RepositoryException)
            {
                this.AddBusinessError(ex);
                return;
            }

            if (ex is BadRequestException)
            {
                this.AddBadRequestError(ex);
            }

            else
            {
                this.SetInternalServerError(ex);
            }
        }

        # endregion
    }
}
